package communication.common.business.heartbeat;


import communication.common.business.base.FcrAutoConfig;
import communication.common.business.base.FcrSocketAddress;
import communication.common.business.base.WorkModeEnum;
import communication.common.vertx.net.NetManager;
import lombok.extern.slf4j.Slf4j;

import java.util.Iterator;
import java.util.Map;

/**
 * 服务端的心跳处理服务。 主要内容是：处理心跳，心跳存活周期性检测 ，发送心跳应答
 * @author mac
 */
@Slf4j
public class HeartBeatServiceOfServer extends HeartBeatServiceCommon{


    /**
     * 有参构造
     *
     * @param netManager             所有socket的连接管理
     */
    public HeartBeatServiceOfServer(NetManager netManager, FcrAutoConfig fcrAutoConfig) throws Exception {
        super(netManager,fcrAutoConfig);
    }

    @Override
    public void setTask() throws Exception {
        checkAllClientHeartBeat();
    }


    /**
     * // 检查是否有client的心跳包超时了
     */
    private void checkAllClientHeartBeat() {
        // 工作模式为server才执行
        if( !this.getFcrAutoConfig().getWorkMode().equals(WorkModeEnum.SERVER) ){
            return;
        }

        long now =System.currentTimeMillis();

        Iterator<Map.Entry<FcrSocketAddress, RecordHeartBeat>> iterator = this.getHeartBeatMap().entrySet().iterator();

        while (iterator.hasNext()){
            Map.Entry<FcrSocketAddress, RecordHeartBeat> next = iterator.next();
            RecordHeartBeat record = next.getValue();
            HeartBeat heartBeat = null ;
            if(record != null && ( heartBeat = record.getHeartBeat()) != null ){

                // 判断是否超时: 当前时间 > 上次心跳的接收时间 + 心跳检查的周期间隔
                boolean timeOutFlg= now > heartBeat.getReceivedTime() + getFcrAutoConfig().getHeartBeat().getInterval();

                if(timeOutFlg){
                    log.warn(" client heartBeat timeOut! address:[{}]",next.getKey().getAddress());
                    record.setTimeOutCount(record.getTimeOutCount()+1);
                }

                // 超时次数超限
                if(record.getTimeOutCount() > getFcrAutoConfig().getHeartBeat().getMaxTimeOut()){
                    iterator.remove();
                    log.warn(" client heartBeat timeOut over Max:{}  , removed heartBeat record  ! address:[{}]",
                            getFcrAutoConfig().getHeartBeat().getMaxTimeOut(),next.getKey().getAddress());
                }
            }

        }

    }





}
